home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / bbs_util / bsrc_260.zip / SRC.ZIP / SBUF.C < prev    next >
C/C++ Source or Header  |  1996-02-20  |  19KB  |  820 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                Box Drawing subroutines for BinkleyTerm                   */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*                                                                          */
  43. /*   This module is derived from code developed by Augie Hansen in his      */
  44. /*   book "Proficient C" published by Microsoft Press.  Mr. Hansen was      */
  45. /*   kind enough to give us verbal permission to use his routines, and      */
  46. /*   Bob, Vince and Alan (and all our full screen users) are grateful.      */
  47. /*   If you decide to use this code in some package you are doing, give     */
  48. /*   some thought to going out and buying the book. He deserves that.       */
  49. /*                                                                          */
  50. /*--------------------------------------------------------------------------*/
  51.  
  52. /* Include this file before any other includes or defines! */
  53.  
  54. #include "includes.h"
  55.  
  56. #include "box.h"
  57. #include "video.h"
  58.  
  59. BUFFER Sbuf;                    /* control information */
  60. CELLP Scrnbuf;                    /* screen buffer array */
  61.  
  62. extern int cursor_col;
  63. extern int cursor_row;
  64.  
  65. #define WHITEBLANK (7 << 8) | ' '
  66.  
  67. static BOXTYPE box[] =
  68. {
  69.     '+', '+', '+', '+', '-', '-', '|', '|',
  70.     ULC11, URC11, LLC11, LRC11, HBAR1, HBAR1, VBAR1, VBAR1,
  71.     ULC22, URC22, LLC22, LRC22, HBAR2, HBAR2, VBAR2, VBAR2,
  72.     ULC12, URC12, LLC12, LRC12, HBAR1, HBAR1, VBAR2, VBAR2,
  73.     ULC21, URC21, LLC21, LRC21, HBAR2, HBAR2, VBAR1, VBAR1,
  74.     BLOCK, BLOCK, BLOCK, BLOCK, HBART, HBARB, BLOCK, BLOCK
  75. };
  76.  
  77. void 
  78. sb_box (REGIONP win, short type, short attr)
  79. {
  80.     register short r;
  81.     short x;
  82.     short maxr, maxc;
  83.     BOXTYPE *boxp;
  84.  
  85.     boxp = &box[type];
  86.     maxc = win->c1 - win->c0;
  87.     maxr = win->r1 - win->r0;
  88.     x = maxc - 1;
  89.  
  90.     /* draw top row */
  91.     sb_move (win, 0, 0);
  92.     sb_wca (win, boxp->ul, attr, 1);
  93.     sb_move (win, 0, 1);
  94.     sb_wca (win, boxp->tbar, attr, x);
  95.     sb_move (win, 0, maxc);
  96.     sb_wca (win, boxp->ur, attr, 1);
  97.  
  98.     /* draw left and right sides */
  99.     for (r = 1; r < maxr; r++)
  100.     {
  101.         sb_move (win, r, 0);
  102.         sb_wca (win, boxp->lbar, attr, 1);
  103.         sb_move (win, r, maxc);
  104.         sb_wca (win, boxp->rbar, attr, 1);
  105.     }
  106.  
  107.     /* draw bottom row */
  108.     sb_move (win, maxr, 0);
  109.     sb_wca (win, boxp->ll, attr, 1);
  110.     sb_move (win, maxr, 1);
  111.     sb_wca (win, boxp->bbar, attr, x);
  112.     sb_move (win, maxr, maxc);
  113.     sb_wca (win, boxp->lr, attr, 1);
  114. }
  115.  
  116. void 
  117. sb_fill (REGIONP win, short ch, short attr)
  118. {
  119.     register short i, j;
  120.     unsigned short ca;
  121.  
  122.     ca = ((unsigned short) attr << 8) | (unsigned short) ch;
  123.  
  124.     for (i = win->sr0; i <= win->sr1; i++)
  125.     {
  126.         for (j = win->sc0; j <= win->sc1; j++)
  127.         {
  128.             (Scrnbuf + i * SB_COLS + j)->cap = ca;
  129.         }
  130.         if (win->sc0 < Sbuf.lcol[i])
  131.         {
  132.             Sbuf.lcol[i] = win->sc0;
  133.         }
  134.         if (win->sc1 > Sbuf.rcol[i])
  135.         {
  136.             Sbuf.rcol[i] = win->sc1;
  137.         }
  138.     }
  139.  
  140.     Sbuf.flags |= SB_DELTA;
  141.     return;
  142. }
  143.  
  144. void 
  145. sb_fillc (REGIONP win, short ch)
  146. {
  147.     register short i, j;
  148.  
  149.     for (i = win->sr0; i <= win->sr1; i++)
  150.     {
  151.         for (j = win->sc0; j <= win->sc1; j++)
  152.         {
  153.             (Scrnbuf + i * SB_COLS + j)->b.ch = (unsigned char) ch;
  154.         }
  155.         if (win->sc0 < Sbuf.lcol[i])
  156.         {
  157.             Sbuf.lcol[i] = win->sc0;
  158.         }
  159.         if (win->sc1 > Sbuf.rcol[i])
  160.         {
  161.             Sbuf.rcol[i] = win->sc1;
  162.         }
  163.     }
  164.  
  165.     Sbuf.flags |= SB_DELTA;
  166.     return;
  167. }
  168.  
  169. void 
  170. sb_filla (REGIONP win, short attr)
  171. {
  172.     register short i, j;
  173.  
  174.     for (i = win->sr0; i <= win->sr1; i++)
  175.     {
  176.         for (j = win->sc0; j <= win->sc1; j++)
  177.         {
  178.             (Scrnbuf + i * SB_COLS + j)->b.attr = (unsigned char) attr;
  179.         }
  180.         if (win->sc0 < Sbuf.lcol[i])
  181.         {
  182.             Sbuf.lcol[i] = win->sc0;
  183.         }
  184.         if (win->sc1 > Sbuf.rcol[i])
  185.         {
  186.             Sbuf.rcol[i] = win->sc1;
  187.         }
  188.     }
  189.  
  190.     Sbuf.flags |= SB_DELTA;
  191.     return;
  192. }
  193.  
  194. void 
  195. sb_init ()
  196. {
  197.     short i, j;
  198.     CELLP c;
  199.     char q[20];
  200.  
  201.     Scrnbuf = (CELLP) calloc ((unsigned short) SB_ROWS * (unsigned short) SB_COLS, sizeof (CELL));
  202.     Sbuf.bp = (CELLP) Scrnbuf;
  203.  
  204.     Sbuf.row = Sbuf.col = 0;
  205.     Sbuf.lcol = (short *) calloc ((unsigned short) SB_COLS, sizeof (short));
  206.     Sbuf.rcol = (short *) calloc ((unsigned short) SB_ROWS, sizeof (short));
  207.  
  208.     (void) sprintf (q, "-%d.%ds", SB_COLS - 16, SB_COLS - 16);
  209.     (void) strcpy (&stat_str[19], q);
  210.     (void) sprintf (q, "-%d.%ds", SB_COLS - 22, SB_COLS - 22);
  211.     (void) strcpy (&script_line[19], q);
  212.  
  213.     if ((Scrnbuf == NULL) ||
  214.         (Sbuf.lcol == NULL) ||
  215.         (Sbuf.rcol == NULL))
  216.     {
  217.         if (Scrnbuf != NULL)
  218.         {
  219.             free (Scrnbuf);
  220.             Scrnbuf = NULL;
  221.         }
  222.         if (Sbuf.lcol != NULL)
  223.         {
  224.             free (Sbuf.lcol);
  225.             Sbuf.lcol = NULL;
  226.         }
  227.         if (Sbuf.rcol != NULL)
  228.         {
  229.             free (Sbuf.rcol);
  230.             Sbuf.rcol = NULL;
  231.         }
  232.  
  233.         SB_ROWS = 23;
  234.         SB_COLS = 80;
  235.  
  236.         Scrnbuf = (CELLP) calloc ((unsigned short) SB_ROWS * (unsigned short) SB_COLS, sizeof (CELL));
  237.         Sbuf.bp = (CELLP) Scrnbuf;
  238.  
  239.         Sbuf.row = Sbuf.col = 0;
  240.         Sbuf.lcol = (short *) calloc ((unsigned short) SB_COLS, sizeof (short));
  241.         Sbuf.rcol = (short *) calloc ((unsigned short) SB_ROWS, sizeof (short));
  242.  
  243.         (void) sprintf (q, "-%d.%ds", SB_COLS - 16, SB_COLS - 16);
  244.         (void) strcpy (&stat_str[19], q);
  245.         (void) sprintf (q, "-%d.%ds", SB_COLS - 22, SB_COLS - 22);
  246.         (void) strcpy (&script_line[19], q);
  247.     }
  248.  
  249.     for (i = 0; i < (short) SB_ROWS; i++)
  250.     {
  251.         Sbuf.lcol[i] = SB_COLS;
  252.         Sbuf.rcol[i] = 0;
  253.     }
  254.  
  255.     Sbuf.flags = 0;
  256.  
  257.     c = Scrnbuf;
  258.     for (i = 0; i < (short) SB_ROWS; i++)
  259.         for (j = 0; j < (short) SB_COLS; j++)
  260.         {
  261.             (*c).cap = WHITEBLANK;
  262.             ++c;
  263.         }
  264.     return;
  265. }
  266.  
  267. void 
  268. sb_move (REGIONP win, register short r, register short c)
  269. {
  270.     /* don't change anything if request is out of range */
  271.     if ((r < 0) || (r > (win->r1 - win->r0)) ||
  272.         (c < 0) || (c > (win->c1 - win->c0)))
  273.         return;                    /* (SB_ERR); */
  274.  
  275.     win->row = r;
  276.     win->col = c;
  277.     Sbuf.row = r + win->r0;
  278.     Sbuf.col = c + win->c0;
  279.  
  280.     return;                        /* (SB_OK); */
  281. }
  282.  
  283. void 
  284. sb_caption (REGIONP Rgn, char *Caption)
  285. {
  286.     sb_move (Rgn, 0, 1);
  287.     sb_puts (Rgn, Caption);
  288. }
  289.  
  290. REGIONP 
  291. sb_new (short top, short left, short height, short width)
  292. {
  293.     REGIONP new;
  294.  
  295.     new = calloc (1, sizeof (REGION));
  296.     if (new != NULL)
  297.     {
  298.         new->r0 = new->sr0 = top;
  299.         new->r1 = new->sr1 = top + height - 1;
  300.         new->c0 = new->sc0 = left;
  301.         new->c1 = new->sc1 = left + width - 1;
  302.         new->row = new->col = 0;
  303.         new->wflags = 0;
  304.     }
  305.     return (new);
  306. }
  307.  
  308. int 
  309. sb_popup (short top, short left, short height, short width,
  310.     int (*func) (BINK_SAVEP, int), int arg)
  311. {
  312.     int x;
  313.     BINK_SAVEP tmp = (BINK_SAVEP) NULL;
  314.  
  315.     if (fullscreen && (un_attended || doing_poll))
  316.     {
  317.  
  318.         tmp = sb_save (top, left, height, width);
  319.         x = (*func) (tmp, arg);
  320.         sb_restore (tmp);
  321.         sb_show ();
  322.     }
  323.     else
  324.     {
  325.         x = (*func) (NULL, arg);
  326.     }
  327.     return (x);
  328. }
  329.  
  330. int 
  331. sb_putc (REGIONP win, short ch)
  332. {
  333.     short cmax, rmax;
  334.     int noscroll = 0, puterr = 0;
  335.  
  336.     /* calculate the screen buffer position and limits */
  337.  
  338.     cmax = win->c1 - win->c0;
  339.     rmax = win->r1 - win->r0;
  340.     Sbuf.row = win->r0 + win->row;
  341.     Sbuf.col = win->c0 + win->col;
  342.  
  343.     /* process the character */
  344.     switch (ch)
  345.     {
  346.     case '\b':
  347.         /* Non destructive backspace */
  348.         if (win->col > 0)
  349.         {
  350.             --(win->col);
  351.             --(Sbuf.col);
  352.             return (SB_OK);
  353.         }
  354.         else
  355.             return (SB_ERR);
  356.  
  357.     case '\r':
  358.         /* clear trailing line segment */
  359.         while (win->col < cmax)
  360.         {
  361.             if (sb_putc (win, ' ') == SB_ERR)
  362.             {
  363.                 ++puterr;
  364.             }
  365.         }
  366.         sb_wc (win, ' ', 1);
  367.         break;
  368.  
  369. #ifdef TABEXP
  370.     case '\t':
  371.         /* convert tabs to spaces */
  372.         lim = win->col + 8 - (win->col & 7);
  373.         while (win->col < lim)
  374.         {
  375.             if (sb_putc (win, ' ') == SB_ERR)
  376.             {
  377.                 ++puterr;
  378.             }
  379.         }
  380.         break;
  381. #endif                            /* TABEXP */
  382.  
  383.     default:
  384.         (Scrnbuf + Sbuf.row * SB_COLS + Sbuf.col)->b.ch = (unsigned char) ch;
  385.  
  386.         if (Sbuf.col < Sbuf.lcol[Sbuf.row])
  387.         {
  388.             Sbuf.lcol[Sbuf.row] = Sbuf.col;
  389.         }
  390.         if (Sbuf.col > Sbuf.rcol[Sbuf.row])
  391.         {
  392.             Sbuf.rcol[Sbuf.row] = Sbuf.col;
  393.         }
  394.         break;
  395.     }
  396.  
  397.     /* update the cursor position */
  398.     if (win->col < cmax)
  399.     {
  400.         ++(win->col);
  401.     }
  402.     else if (win->row < rmax)
  403.     {
  404.         win->col = 0;
  405.         ++(win->row);
  406.     }
  407.     else if (win->wflags & SB_SCROLL)
  408.     {
  409.         sb_scrl (win, 1);
  410.         win->col = 0;
  411.         win->row = rmax;
  412.     }
  413.     else
  414.     {
  415.         ++noscroll;
  416.     }
  417.  
  418.     /* update screen buffer position */
  419.     Sbuf.row = win->r0 + win->row;
  420.     Sbuf.col = win->c0 + win->col;
  421.     Sbuf.flags |= SB_DELTA;
  422.  
  423.     return ((noscroll || puterr) ? SB_ERR : SB_OK);
  424. }
  425.  
  426. void 
  427. sb_puts (REGIONP win, char *s)
  428. {
  429.     while (*s)
  430.     {
  431.         if (sb_putc (win, *s++) == SB_ERR)
  432.             return;                /* (SB_ERR); */
  433.     }
  434.  
  435.     return;                        /* (SB_OK); */
  436. }
  437.  
  438. unsigned char 
  439. sb_ra (REGIONP win, short r, short c)
  440. {
  441.     return ((unsigned char) (Scrnbuf + (win->r0 + r) * SB_COLS + win->c0 + c)->b.attr);
  442. }
  443.  
  444. unsigned char 
  445. sb_rc (REGIONP win, short r, short c)
  446. {
  447.     return ((unsigned char) (Scrnbuf + (win->r0 + r) * SB_COLS + win->c0 + c)->b.ch);
  448. }
  449.  
  450. unsigned int 
  451. sb_rca (REGIONP win, short r, short c)
  452. {
  453.     return ((unsigned int) (Scrnbuf + (win->r0 + r) * SB_COLS + win->c0 + c)->cap);
  454. }
  455.  
  456. int 
  457. sb_input_chars (REGIONP win, short row, short col, char *str, short len)
  458. {
  459.     short i;
  460.     short j;
  461.  
  462.     sb_move (win, row, col);
  463.     for (i = 0; i < len; i++)
  464.         (void) sb_putc (win, '_');
  465.     sb_move (win, row, col);
  466.  
  467.     i = 0;
  468.     while (i < len)
  469.     {
  470.         sb_show ();
  471.         while (!KEYPRESS ())
  472.             time_release ();
  473.         j = FOSSIL_CHAR ();
  474.         if ((j & 0xff) != 0)
  475.         {
  476.             j &= 0xff;
  477.             j = toupper (j);
  478.             if (isprint (j))
  479.             {
  480.                 (void) sb_putc (win, (short) (j & 0xff));
  481.                 *str = (char) (j & 0xff);
  482.                 ++str;
  483.                 ++i;
  484.                 ++col;
  485.                 continue;
  486.             }
  487.         }
  488.  
  489.         switch (j)
  490.         {
  491.         case ESC:
  492.             return (1);
  493.  
  494.         case BS:
  495.         case LFAR:
  496.             if (i > 0)
  497.             {
  498.                 --col;
  499.                 sb_move (win, row, col);
  500.                 (void) sb_putc (win, '_');
  501.                 sb_move (win, row, col);
  502.                 --str;
  503.                 --i;
  504.             }
  505.             break;
  506.  
  507.         case CR:
  508.         case LV:
  509.             *str = '\0';
  510.             for (j = i; j < len; j++)
  511.                 (void) sb_putc (win, ' ');
  512.  
  513.             if (i)
  514.                 return (0);
  515.             else
  516.                 return (1);
  517.         }
  518.     }
  519.  
  520.     *str = '\0';
  521.     sb_show ();
  522.     return (0);
  523. }
  524.  
  525. BINK_SAVEP 
  526. sb_save (short top, short left, short height, short width)
  527. {
  528.     BINK_SAVEP new;
  529.     CELLP c;
  530.     short i, j;
  531.  
  532.     new = calloc (1, sizeof (BINK_SAVE));
  533.     c = new->save_cells = (CELLP) malloc (sizeof (CELL) * height * width);
  534.     new->region = sb_new (top, left, height, width);
  535.     new->save_row = (short) top;
  536.     new->save_col = (short) left;
  537.     new->save_ht = (short) height;
  538.     new->save_wid = (short) width;
  539.  
  540.     j = top * SB_COLS + left;
  541.     for (i = 0; i < height; i++)
  542.     {
  543.         (void) memcpy (&c[i * width], &Scrnbuf[j], width * sizeof (CELL));
  544.         j += SB_COLS;
  545.     }
  546.  
  547.     return (new);
  548. }
  549.  
  550. void 
  551. sb_restore (BINK_SAVEP save)
  552. {
  553.     short i, j, r;
  554.  
  555.     j = save->save_row * SB_COLS + save->save_col;
  556.     for (r = save->save_row, i = 0; i < save->save_ht; r++, i++)
  557.     {
  558.         (void) memcpy (&Scrnbuf[j], &(save->save_cells[i * save->save_wid]), save->save_wid * sizeof (CELL));
  559.         j += SB_COLS;
  560.         if (save->save_col < Sbuf.lcol[r])
  561.             Sbuf.lcol[r] = save->save_col;
  562.         if (save->save_col + save->save_wid > Sbuf.rcol[r])
  563.             Sbuf.rcol[r] = save->save_col + save->save_wid;
  564.     }
  565.  
  566.     Sbuf.flags |= SB_DELTA;
  567.  
  568.     free ((char *) (save->save_cells));
  569.     free (save->region);
  570.     free (save);
  571. }
  572.  
  573. void 
  574. sb_scrl (REGIONP win, short n)
  575. {
  576.     register short r, c;
  577.  
  578.     c = win->sc0;
  579.     if (n == 0)
  580.     {
  581.         /* clear the entire region to spaces */
  582.         sb_fillc (win, ' ');
  583.     }
  584.     else if (n > 0)
  585.     {
  586.         /* scroll n rows up */
  587.         for (r = win->sr0; r <= win->sr1 - n; r++)
  588.         {
  589.             (void) memcpy (Scrnbuf + r * SB_COLS + c, Scrnbuf + (r + n) * SB_COLS + c,
  590.                 (unsigned short) (win->sc1 - win->sc0 + 1) * 2);
  591.  
  592.             if (win->sc0 < Sbuf.lcol[r])
  593.             {
  594.                 Sbuf.lcol[r] = win->sc0;
  595.             }
  596.             if (win->sc1 > Sbuf.rcol[r])
  597.             {
  598.                 Sbuf.rcol[r] = win->sc1;
  599.             }
  600.         }
  601.         for (; r <= win->sr1; r++)
  602.         {
  603.             for (c = win->sc0; c <= win->sc1; c++)
  604.             {
  605.                 (Scrnbuf + r * SB_COLS + c)->b.ch = ' ';
  606.             }
  607.             if (win->sc0 < Sbuf.lcol[r])
  608.             {
  609.                 Sbuf.lcol[r] = win->sc0;
  610.             }
  611.             if (win->sc1 > Sbuf.rcol[r])
  612.             {
  613.                 Sbuf.rcol[r] = win->sc1;
  614.             }
  615.         }
  616.     }
  617.     else
  618.     {
  619.         /* scroll n rows down */
  620.         n = -n;
  621.         for (r = win->sr1; r >= win->sr0 + n; r--)
  622.         {
  623.             (void) memcpy (Scrnbuf + r * SB_COLS + c, Scrnbuf + (r - n) * SB_COLS + c,
  624.                 (unsigned short) (win->sc1 - win->sc0 + 1) * 2);
  625.             if (win->sc0 < Sbuf.lcol[r])
  626.             {
  627.                 Sbuf.lcol[r] = win->sc0;
  628.             }
  629.             if (win->sc1 > Sbuf.rcol[r])
  630.             {
  631.                 Sbuf.rcol[r] = win->sc1;
  632.             }
  633.         }
  634.         for (; r >= win->sr0; r--)
  635.         {
  636.             for (c = win->sc0; c <= win->sc1; c++)
  637.             {
  638.                 (Scrnbuf + r * SB_COLS + c)->b.ch = ' ';
  639.             }
  640.             if (win->sc0 < Sbuf.lcol[r])
  641.             {
  642.                 Sbuf.lcol[r] = win->sc0;
  643.             }
  644.             if (win->sc1 > Sbuf.rcol[r])
  645.             {
  646.                 Sbuf.rcol[r] = win->sc1;
  647.             }
  648.         }
  649.     }
  650.  
  651.     Sbuf.flags |= SB_DELTA;
  652.  
  653.     return;
  654. }
  655.  
  656. void 
  657. sb_show ()
  658. {
  659.     register short r;
  660.     unsigned short src_os;
  661.     char far *q;
  662.  
  663.     if (screen_blank && do_screen_blank)
  664.     {
  665.         for (r = 0; r < SB_ROWS; r++)
  666.         {
  667.             q = blanks;
  668.             (void) VioWrtCellStr ((PCH) q, (USHORT) (SB_COLS * 2), (USHORT) r, (USHORT) 0, (HVIO) 0L);
  669.         }
  670.         sb_dirty ();
  671.         return;
  672.     }
  673.  
  674.     /* Anything to do? */
  675.     if (!(Sbuf.flags & SB_DELTA))
  676.     {
  677.         return;
  678.     }
  679.  
  680.     src_os = 0;
  681.     for (r = 0; r < SB_ROWS; r++)
  682.     {
  683.         /* Copy only changed portions of lines */
  684.         if ((Sbuf.lcol[r] < SB_COLS) && (Sbuf.rcol[r] > 0))
  685.         {
  686.             q = (char far *) (Scrnbuf + src_os + Sbuf.lcol[r]);
  687.             (void) VioWrtCellStr ((PCH) q, (USHORT) ((Sbuf.rcol[r] - Sbuf.lcol[r] + 1) * 2), (USHORT) r, (USHORT) Sbuf.lcol[r], (HVIO) 0L);
  688.             Sbuf.lcol[r] = SB_COLS;
  689.             Sbuf.rcol[r] = 0;
  690.         }
  691.         src_os += (unsigned short) SB_COLS;
  692.     }
  693.  
  694.     /* the display now matches the buffer -- clear flag bit */
  695.     Sbuf.flags &= ~SB_DELTA;
  696.  
  697.     /* Put sanity check on cursor_row and cursor_col here */
  698.     if (cursor_row < 0 || cursor_row > (short) (SB_ROWS - 1))
  699.         cursor_row = SB_ROWS - 1;
  700.     if (cursor_col < 0 || cursor_col > (short) (SB_COLS - 1))
  701.         cursor_col = SB_COLS - 1;
  702.  
  703.     gotoxy (cursor_col, cursor_row);
  704.     return;
  705. }
  706.  
  707. /*
  708.  * Just cleans up the structure to say it is reality - I can use this when
  709.  * I write directly to the screen for single char writes.
  710.  */
  711.  
  712. void 
  713. sb_clean ()
  714. {
  715.     short r;
  716.  
  717.     for (r = 0; r < (short) SB_ROWS; r++)
  718.     {
  719.         Sbuf.lcol[r] = SB_COLS;
  720.         Sbuf.rcol[r] = 0;
  721.     }
  722.  
  723.     Sbuf.flags &= ~SB_DELTA;
  724. }
  725.  
  726. /*
  727.  * Make the entire buffer "dirty" so it will be updated.
  728.  */
  729.  
  730. void 
  731. sb_dirty ()
  732. {
  733.     short r;
  734.  
  735.     for (r = 0; r < (short) SB_ROWS; r++)
  736.     {
  737.         Sbuf.lcol[r] = 0;
  738.         Sbuf.rcol[r] = SB_COLS_M_1;
  739.     }
  740.  
  741.     Sbuf.flags |= SB_DELTA;
  742. }
  743.  
  744. void 
  745. sb_wa (REGIONP win, short attr, short n)
  746. {
  747.     short i;
  748.     short row;
  749.     short col;
  750.  
  751.     i = n;
  752.     row = win->r0 + win->row;
  753.     col = win->c0 + win->col;
  754.  
  755.     while (i--)
  756.         (Scrnbuf + row * SB_COLS + col + i)->b.attr = (unsigned char) attr;
  757.  
  758.     /* marked the changed region */
  759.     if (col < Sbuf.lcol[row])
  760.         Sbuf.lcol[row] = col;
  761.     if (col + n > Sbuf.rcol[row])
  762.         Sbuf.rcol[row] = col + n;
  763.  
  764.     Sbuf.flags |= SB_DELTA;
  765.  
  766.     return;                        /* ((i == 0) ? SB_OK : SB_ERR); */
  767. }
  768.  
  769. void 
  770. sb_wc (REGIONP win, short ch, short n)
  771. {
  772.     short i;
  773.     short row;
  774.     short col;
  775.  
  776.     i = n;
  777.     row = win->r0 + win->row;
  778.     col = win->c0 + win->col;
  779.  
  780.     while (i--)
  781.         (Scrnbuf + row * SB_COLS + col + i)->b.ch = (unsigned char) ch;
  782.  
  783.     /* marked the changed region */
  784.     if (col < Sbuf.lcol[row])
  785.         Sbuf.lcol[row] = col;
  786.     if (col + n > Sbuf.rcol[row])
  787.         Sbuf.rcol[row] = col + n;
  788.  
  789.     Sbuf.flags |= SB_DELTA;
  790.  
  791.     return;                        /* ((i == 0) ? SB_OK : SB_ERR); */
  792. }
  793.  
  794. void 
  795. sb_wca (REGIONP win, short ch, short attr, short n)
  796. {
  797.     short i;
  798.     short row;
  799.     short col;
  800.     unsigned short ca;
  801.  
  802.     i = n;
  803.     ca = (((unsigned short) attr) << 8) | (unsigned short) ch;
  804.     row = win->r0 + win->row;
  805.     col = win->c0 + win->col;
  806.  
  807.     while (i--)
  808.         (Scrnbuf + row * SB_COLS + col + i)->cap = ca;
  809.  
  810.     /* marked the changed region */
  811.     if (col < Sbuf.lcol[row])
  812.         Sbuf.lcol[row] = col;
  813.     if (col + n > Sbuf.rcol[row])
  814.         Sbuf.rcol[row] = col + n;
  815.  
  816.     Sbuf.flags |= SB_DELTA;
  817.  
  818.     return;                        /* ((i == 0) ? SB_OK : SB_ERR); */
  819. }
  820.